<template>
  <div class="custom-component-editor">
    <div class="editor-header">
      <h3>自定义组件编辑器</h3>
      <div class="header-actions">
        <el-button @click="previewComponent">预览</el-button>
        <el-button type="primary" @click="saveComponent">保存</el-button>
        <el-button @click="exportComponent">导出</el-button>
      </div>
    </div>

    <div class="editor-main">
      <!-- 左侧工具栏 -->
      <div class="toolbar">
        <div class="toolbar-section">
          <h4>基础元素</h4>
          <div class="element-list">
            <div
              v-for="element in basicElements"
              :key="element.type"
              class="element-item"
              draggable="true"
              @dragstart="handleDragStart($event, element)"
            >
              <i :class="element.icon"></i>
              <span>{{ element.name }}</span>
            </div>
          </div>
        </div>
      </div>

      <!-- 中间画布 -->
      <div class="canvas">
        <div class="canvas-header">
          <span>画布 ({{ canvasWidth }} × {{ canvasHeight }})</span>
          <div class="canvas-tools">
            <el-button size="small" @click="zoomIn">放大</el-button>
            <el-button size="small" @click="zoomOut">缩小</el-button>
            <el-button size="small" @click="resetZoom">重置</el-button>
          </div>
        </div>

        <div
          class="canvas-container"
          :style="{ transform: `scale(${zoom})` }"
          @dragover="handleDragOver"
          @drop="handleDrop"
          @click="clearSelection"
        >
          <div class="canvas-content" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }">
            <div
              v-for="element in canvasElements"
              :key="element.id"
              class="canvas-element"
              :class="{ selected: selectedElement?.id === element.id }"
              :style="getElementStyle(element)"
              @click.stop="selectElement(element)"
            >
              <component :is="getElementComponent(element.type)" v-bind="element.props" />
              
              <div v-if="selectedElement?.id === element.id" class="element-actions">
                <el-button size="mini" @click.stop="duplicateElement(element)">复制</el-button>
                <el-button size="mini" type="danger" @click.stop="deleteElement(element)">删除</el-button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 右侧属性面板 -->
      <div class="panel">
        <div class="panel-header">
          <h4>属性设置</h4>
        </div>
        
        <div v-if="selectedElement" class="panel-content">
          <el-form label-width="80px" size="small">
            <el-form-item label="位置X">
              <el-input-number v-model="selectedElement.x" @change="updateElement" />
            </el-form-item>
            <el-form-item label="位置Y">
              <el-input-number v-model="selectedElement.y" @change="updateElement" />
            </el-form-item>
            <el-form-item label="宽度">
              <el-input-number v-model="selectedElement.width" @change="updateElement" />
            </el-form-item>
            <el-form-item label="高度">
              <el-input-number v-model="selectedElement.height" @change="updateElement" />
            </el-form-item>
          </el-form>
        </div>
        
        <div v-else class="panel-empty">
          <p>请选择一个元素</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'

interface CanvasElement {
  id: string
  type: string
  x: number
  y: number
  width: number
  height: number
  props: Record<string, any>
}

interface DragElement {
  type: string
  name: string
  icon: string
  defaultProps: Record<string, any>
}

// 响应式数据
const zoom = ref(1)
const canvasWidth = ref(800)
const canvasHeight = ref(600)
const canvasElements = ref<CanvasElement[]>([])
const selectedElement = ref<CanvasElement | null>(null)

// 基础元素
const basicElements: DragElement[] = [
  {
    type: 'text',
    name: '文本',
    icon: 'el-icon-document',
    defaultProps: { content: '文本内容' }
  },
  {
    type: 'button',
    name: '按钮',
    icon: 'el-icon-thumb',
    defaultProps: { text: '按钮' }
  },
  {
    type: 'input',
    name: '输入框',
    icon: 'el-icon-edit',
    defaultProps: { placeholder: '请输入内容' }
  }
]

// 方法
const handleDragStart = (event: DragEvent, element: DragElement) => {
  if (event.dataTransfer) {
    event.dataTransfer.setData('text/plain', JSON.stringify(element))
  }
}

const handleDragOver = (event: DragEvent) => {
  event.preventDefault()
}

const handleDrop = (event: DragEvent) => {
  event.preventDefault()
  
  if (event.dataTransfer) {
    const elementData = event.dataTransfer.getData('text/plain')
    if (elementData) {
      const element = JSON.parse(elementData) as DragElement
      const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()
      const x = (event.clientX - rect.left) / zoom.value
      const y = (event.clientY - rect.top) / zoom.value
      
      addElement(element, x, y)
    }
  }
}

const addElement = (element: DragElement, x: number, y: number) => {
  const newElement: CanvasElement = {
    id: Date.now().toString(),
    type: element.type,
    x: Math.max(0, x - 50),
    y: Math.max(0, y - 30),
    width: 100,
    height: 60,
    props: { ...element.defaultProps }
  }
  
  canvasElements.value.push(newElement)
  selectElement(newElement)
}

const selectElement = (element: CanvasElement) => {
  selectedElement.value = element
}

const clearSelection = () => {
  selectedElement.value = null
}

const updateElement = () => {
  // 元素更新时会自动触发响应式更新
}

const duplicateElement = (element: CanvasElement) => {
  const newElement: CanvasElement = {
    ...element,
    id: Date.now().toString(),
    x: element.x + 20,
    y: element.y + 20
  }
  canvasElements.value.push(newElement)
  selectElement(newElement)
}

const deleteElement = (element: CanvasElement) => {
  const index = canvasElements.value.findIndex(e => e.id === element.id)
  if (index > -1) {
    canvasElements.value.splice(index, 1)
    if (selectedElement.value?.id === element.id) {
      selectedElement.value = null
    }
  }
}

const getElementStyle = (element: CanvasElement) => {
  return {
    position: 'absolute',
    left: element.x + 'px',
    top: element.y + 'px',
    width: element.width + 'px',
    height: element.height + 'px'
  }
}

const getElementComponent = (type: string) => {
  const componentMap: Record<string, string> = {
    'text': 'div',
    'button': 'el-button',
    'input': 'el-input'
  }
  return componentMap[type] || 'div'
}

const zoomIn = () => {
  zoom.value = Math.min(zoom.value + 0.1, 2)
}

const zoomOut = () => {
  zoom.value = Math.max(zoom.value - 0.1, 0.1)
}

const resetZoom = () => {
  zoom.value = 1
}

const previewComponent = () => {
  ElMessage.info('预览功能开发中')
}

const saveComponent = () => {
  const componentData = {
    elements: canvasElements.value,
    width: canvasWidth.value,
    height: canvasHeight.value
  }
  
  localStorage.setItem('custom-component-' + Date.now(), JSON.stringify(componentData))
  ElMessage.success('组件保存成功')
}

const exportComponent = () => {
  const componentData = {
    elements: canvasElements.value,
    width: canvasWidth.value,
    height: canvasHeight.value
  }
  
  const dataStr = JSON.stringify(componentData, null, 2)
  const dataBlob = new Blob([dataStr], { type: 'application/json' })
  const url = URL.createObjectURL(dataBlob)
  const link = document.createElement('a')
  link.href = url
  link.download = 'custom-component.json'
  link.click()
  URL.revokeObjectURL(url)
  ElMessage.success('组件导出成功')
}
</script>

<style scoped>
.custom-component-editor {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: #f5f7fa;
}

.editor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background: white;
  border-bottom: 1px solid #e4e7ed;
}

.editor-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #303133;
}

.header-actions {
  display: flex;
  gap: 12px;
}

.editor-main {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.toolbar {
  width: 250px;
  background: white;
  border-right: 1px solid #e4e7ed;
  padding: 16px;
}

.toolbar-section h4 {
  margin: 0 0 12px 0;
  font-size: 14px;
  font-weight: 600;
  color: #303133;
}

.element-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.element-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  cursor: grab;
  transition: all 0.2s;
  background: white;
}

.element-item:hover {
  border-color: #409eff;
  background: #f0f9ff;
}

.element-item i {
  font-size: 16px;
  color: #409eff;
}

.canvas {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: #f0f0f0;
}

.canvas-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: white;
  border-bottom: 1px solid #e4e7ed;
}

.canvas-container {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  padding: 20px;
}

.canvas-content {
  position: relative;
  background: white;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  border-radius: 4px;
}

.canvas-element {
  position: absolute;
  cursor: pointer;
  border: 1px solid transparent;
  transition: all 0.2s;
}

.canvas-element:hover {
  border-color: #409eff;
}

.canvas-element.selected {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.3);
}

.element-actions {
  position: absolute;
  top: -30px;
  right: 0;
  display: flex;
  gap: 4px;
  background: white;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 4px;
}

.panel {
  width: 300px;
  background: white;
  border-left: 1px solid #e4e7ed;
}

.panel-header {
  padding: 16px;
  border-bottom: 1px solid #e4e7ed;
}

.panel-header h4 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.panel-content {
  padding: 16px;
}

.panel-empty {
  padding: 16px;
  text-align: center;
  color: #909399;
}
</style> 